package com.xinzhidi.web.netty.service;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinzhidi.common.constant.AgreementConstants;
import com.xinzhidi.common.utils.DateUtils;
import com.xinzhidi.common.utils.StringUtils;
import com.xinzhidi.common.utils.file.FileTypeUtils;
import com.xinzhidi.web.build.domain.BuildUnit;
import com.xinzhidi.web.netty.entity.*;
import com.xinzhidi.web.netty.entity.dto.AgreementBuildValveListDto;
import com.xinzhidi.web.netty.entity.dto.AgreementUnitValveListDto;
import com.xinzhidi.web.netty.mapper.AgreementBuildValveMapper;
import com.xinzhidi.web.netty.utils.NettyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 楼栋阀门协议-（实时数据）Service业务层处理
 * 
 * @author cx
 * @date 2023-12-19
 */
@Service
public class AgreementBuildValveService extends ServiceImpl<AgreementBuildValveMapper, AgreementBuildValve> {

    @Autowired
    private AgreementCommandService commandService;

    @Autowired
    private AgreementCommandFieldService commandFieldService;

    @Autowired
    private AgreementBuildValveHistoryService buildValveHistoryService;

    @Autowired
    private DeviceInstructionService deviceInstructionService;

    /**
     * 楼栋阀门协议解析
     *
     * @param deviceInstruction 下发指令
     * @param message           消息
     */
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> receiveBuildValve(String message, DeviceInstruction deviceInstruction) {
        //        LambdaQueryWrapper<AgreementUnitValveHistory> wrapper = new LambdaQueryWrapper<>();
//        wrapper.orderByDesc(AgreementUnitValveHistory::getCreateTime).last(" limit 1");

        LambdaQueryWrapper<AgreementCommand> commandWrapper = new LambdaQueryWrapper<>();
        commandWrapper.eq(AgreementCommand::getType, AgreementConstants.InstructionType.RECEIVE)
                .eq(AgreementCommand::getProtocolType, deviceInstruction.getProtocolType())
                .eq(AgreementCommand::getInstructType, deviceInstruction.getInstructType());
        AgreementCommand command = commandService.getOne(commandWrapper);

        LambdaQueryWrapper<AgreementCommandField> commandFieldLambdaQueryWrapper = new LambdaQueryWrapper<>();
        commandFieldLambdaQueryWrapper.eq(AgreementCommandField::getCommandId, command.getId())
                .orderByAsc(AgreementCommandField::getSort);
        List<AgreementCommandField> commandFieldList = commandFieldService.list(commandFieldLambdaQueryWrapper);
        Map<String, Object> map = new HashMap<>();
        for (AgreementCommandField commandField : commandFieldList) {
            Integer startNum = commandField.getStartNum();
            Integer endNum = commandField.getEndNum();
            String value = NettyUtils.getByteStr(startNum, endNum, message, commandField);
            FileTypeUtils.setValueByType(commandField.getFieldEnglish(), commandField.getFieldType(), map, value);
        }
        //保存楼栋阀门协议-实时数据表（agreement_build_valve）、楼栋阀门协议-历史数据表（agreement_build_valve_history）
        saveAgreementBuildValve(message, map, command, deviceInstruction);
        return map;
    }

    /**
     * 保存楼栋阀门协议-实时数据表（agreement_build_valve）、楼栋阀门协议-历史数据表（agreement_build_valve_history）
     */
    private Map<String, Object> saveAgreementBuildValve(String message, Map<String, Object> map, AgreementCommand command, DeviceInstruction deviceInstruction) {
        AgreementBuildValve buildValve;
        //判断单元阀门实时数据是否已存在，存在则更新，不存在则新增
        AgreementBuildValveListDto dto = new AgreementBuildValveListDto();
        dto.setDtuId(deviceInstruction.getDtuId());
        dto.setAddress(deviceInstruction.getAddress());
        dto.setInstructType(command.getInstructType());
        buildValve = this.getAgreementBuildValve(dto);
        String dataFieldSerialNumber = this.getDataFieldSerialNumber(dto);
        if (buildValve != null) {
            buildValve.setInstructionSet(message);
            buildValve.setJsonData(JSON.toJSONString(map));
            buildValve.setUpdateTime(DateUtils.getNowDate());
        } else {
            buildValve = new AgreementBuildValve();
            buildValve.setDeviceInstructionId(deviceInstruction.getId());
            buildValve.setDtuId(deviceInstruction.getDtuId());
            buildValve.setProtocolName(command.getProtocolName());
            buildValve.setInstructType(command.getInstructType());
            buildValve.setInstructName(command.getInstructName());
            buildValve.setPlotId(deviceInstruction.getPlotId());
            buildValve.setBuildId(deviceInstruction.getBuildId());
            buildValve.setUnitId(deviceInstruction.getUnitId());
            buildValve.setHouseholdId(deviceInstruction.getHouseholdId());
            buildValve.setDeviceType(command.getDeviceType());
            buildValve.setAddress(deviceInstruction.getAddress());
            buildValve.setInstructionSet(message);
            buildValve.setJsonData(JSON.toJSONString(map));
        }
        buildValve.setDataFieldSerialNumber(dataFieldSerialNumber);
        if (this.saveOrUpdate(buildValve)) {
            LambdaQueryWrapper<AgreementCommand> commandWrapper = new LambdaQueryWrapper<>();
            commandWrapper.eq(AgreementCommand::getType, AgreementConstants.InstructionType.RECEIVE)
                    .eq(AgreementCommand::getProtocolType, deviceInstruction.getProtocolType())
                    .eq(AgreementCommand::getInstructType, deviceInstruction.getInstructType());
            command = commandService.getOne(commandWrapper);
            //保存楼栋阀门协议-历史数据表（agreement_build_valve_history）
            AgreementBuildValveHistory buildValveHistory = new AgreementBuildValveHistory();
            buildValveHistory.setDeviceInstructionId(deviceInstruction.getId());
            buildValveHistory.setDtuId(deviceInstruction.getDtuId());
            buildValveHistory.setProtocolName(command.getProtocolName());
            buildValveHistory.setInstructType(command.getInstructType());
            buildValveHistory.setInstructName(command.getInstructName());
            buildValveHistory.setPlotId(deviceInstruction.getPlotId());
            buildValveHistory.setBuildId(deviceInstruction.getBuildId());
            buildValveHistory.setUnitId(deviceInstruction.getUnitId());
            buildValveHistory.setHouseholdId(deviceInstruction.getHouseholdId());
            buildValveHistory.setDeviceType(command.getDeviceType());
            buildValveHistory.setAddress(deviceInstruction.getAddress());
            buildValveHistory.setInstructionSet(message);
            buildValveHistory.setPrefix(command.getPrefix());
            buildValveHistory.setDeviceType(command.getDeviceType());
            buildValveHistory.setControlCode(command.getControlCode());
            buildValveHistory.setLengthField(command.getLengthField());
            buildValveHistory.setStartChar(command.getStartChar());
            buildValveHistory.setJsonData(JSON.toJSONString(map));
            buildValveHistory.setDataFieldMark(command.getDataMark());
            buildValveHistory.setEndMark(command.getEndMark());
            buildValveHistory.setDataFieldSerialNumber(dataFieldSerialNumber);
            buildValveHistoryService.save(buildValveHistory);
        }
        deviceInstruction.setStatus(AgreementConstants.InstructSendingState.RETURN_TO_NORMAL);
        deviceInstructionService.updateById(deviceInstruction);
        return map;
    }

    public AgreementBuildValve getAgreementBuildValve(AgreementBuildValveListDto dto) {
        AgreementBuildValve buildValveValve = this.baseMapper.selectOne(buildGenTableQueryWrapper(dto));
        return buildValveValve;
    }

    private LambdaQueryWrapper<AgreementBuildValve> buildGenTableQueryWrapper(AgreementBuildValveListDto dto) {
        LambdaQueryWrapper<AgreementBuildValve> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.isNotBlank(dto.getProtocolName()), AgreementBuildValve::getProtocolName, dto.getProtocolName())
                .like(StringUtils.isNotBlank(dto.getInstructName()), AgreementBuildValve::getInstructName, dto.getInstructName())
                .eq(StringUtils.isNotBlank(dto.getInstructType()), AgreementBuildValve::getInstructType, dto.getInstructType())
                .eq(StringUtils.isNotNull(dto.getDtuId()), AgreementBuildValve::getDtuId, dto.getDtuId())
                .eq(StringUtils.isNotBlank(dto.getAddress()), AgreementBuildValve::getAddress, dto.getAddress());
        return wrapper;
    }

    /**
     * 获取序列号---dataFieldSerialNumber
     */
    public String getDataFieldSerialNumber(AgreementBuildValveListDto dto) {
        Integer number = 0;
        AgreementBuildValve buildValve = this.getAgreementBuildValve(dto);
        if (buildValve == null) {
            return number.toString();
        }

        number = Integer.valueOf(buildValve.getDataFieldSerialNumber());
        if (number == 256) {
            number = 0;
        } else {
            number++;
        }

        return String.valueOf(number);
    }
}
